# -*- coding: utf-8 -*-
# @Time : 2024/2/2 10:33
# @Author : ZH
# @File : target_info.py
# @Software: PyCharm
import json
import logging
import math
from typing import List
from urllib.parse import urlencode

import numpy as np


class LoggingInfo:
    def __init__(self):
        # 创建logger对象
        self.logger = logging.getLogger()

        # 设置日志输出到控制台
        console_handler = logging.StreamHandler()
        formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
        console_handler.setFormatter(formatter)
        self.logger.addHandler(console_handler)

        # 设置日志等级为DEBUG
        self.logger.setLevel(logging.DEBUG)


class TargetInfo(object):
    """
    搜索指定范围内的指定名称的目标信息，比如：故宫  113.58762 37.86236
    获取指定目标的图片、视频、街景id
    """

    def __init__(self):
        self.logging_info = LoggingInfo().logger
        self.logging_info.info('*' * 10)
        self.logging_info.info('天王盖地虎')
        self.logging_info.info('*' * 10)
        # 经纬度和距离互转
        # 来源：https://blog.csdn.net/qq_37742059/article/details/101554565
        self.earth_radius = 6370.856  # 地球平均半径，单位km，最简单的模型往往把地球当做完美的球形，这个值就是常说的RE
        self.math_2pi = math.pi * 2
        self.pis_per_degree = self.math_2pi / 360  # 角度一度所对应的弧度数，360对应2*pi
        # 谷歌地图英文国家
        self.google_country_dict = {'afghanistan': 'Afghanistan', 'åland islands': 'Åland Islands',
                                    'albania': 'Albania',
                                    'algeria': 'Algeria', 'american samoa': 'American Samoa', 'andorra': 'Andorra',
                                    'angola': 'Angola', 'anguilla': 'Anguilla', 'antarctica': 'Antarctica',
                                    'antigua and barbuda': 'Antigua and Barbuda', 'argentina': 'Argentina',
                                    'armenia': 'Armenia', 'aruba': 'Aruba', 'australia': 'Australia',
                                    'austria': 'Austria',
                                    'azerbaijan': 'Azerbaijan', 'bahamas': 'The Bahamas', 'bahrain': 'Bahrain',
                                    'bangladesh': 'Bangladesh', 'barbados': 'Barbados', 'belarus': 'Belarus',
                                    'belgium': 'Belgium', 'belize': 'Belize', 'benin': 'Benin', 'bermuda': 'Bermuda',
                                    'bhutan': 'Bhutan', 'bolivia': 'Bolivia',
                                    'bonaire, sint eustatius and saba (netherlands)': 'Sint Eustatius',
                                    'bosnia and herzegovina': 'Bosnia and Herzegovina', 'botswana': 'Botswana',
                                    'bouvet island': 'Bouvet Island', 'brazil': 'Brazil',
                                    'british indian ocean territory': 'British Indian Ocean Territory',
                                    'brunei darussalam': 'Brunei', 'brunei': 'Brunei', 'bulgaria': 'Bulgaria',
                                    'burkina faso': 'Burkina Faso', 'burundi': 'Burundi', 'cape verde': 'Cape Verde',
                                    'cambodia': 'Cambodia', 'cameroon': 'Cameroon', 'canada': 'Canada',
                                    'cayman islands': 'Cayman Islands', 'central african': 'Central African Republic',
                                    'central african republic': 'Central African Republic', 'chad': 'Chad',
                                    'chile': 'Chile',
                                    'china': 'China', 'christmas island': 'Christmas Island', 'colombia': 'Colombia',
                                    'comoros': 'Comoros',
                                    'democratic republic of congo': 'Democratic Republic of the Congo',
                                    'congo dr': 'Democratic Republic of the Congo',
                                    'congo': 'Democratic Republic of the Congo', 'cook islands': 'Cook Islands',
                                    'costa rica': 'Costa Rica', 'croatia': 'Croatia', 'cuba': 'Cuba',
                                    'curaçao': 'Curaçao',
                                    'cyprus': 'Cyprus', 'czech republic': 'Czechia', 'denmark': 'Denmark',
                                    'djibouti': 'Djibouti', 'dominica': 'Dominica',
                                    'dominican rep': 'Dominican Republic',
                                    'dominican republic': 'Dominican Republic', 'ecuador': 'Ecuador', 'egypt': 'Egypt',
                                    'el salvador': 'El Salvador', 'equatorial guinea': 'Equatorial Guinea',
                                    'eritrea': 'Eritrea', 'estonia': 'Estonia', 'ethiopia': 'Ethiopia',
                                    'falkland islands  [malvinas]': 'Falkland Islands (Islas Malvinas)',
                                    'faroe islands (denmark)': 'Faroe Islands', 'fiji': 'Fiji', 'finland': 'Finland',
                                    'france': 'France', 'french guiana (france)': 'French Guiana',
                                    'french polynesia (france)': 'French Polynesia',
                                    'french southern territories': 'French Southern and Antarctic Lands',
                                    'gabon': 'Gabon',
                                    'gambia': 'The Gambia', 'georgia': 'Georgia', 'germany': 'Germany',
                                    'ghana': 'Ghana',
                                    'gibraltar': 'Gibraltar', 'greece': 'Greece', 'greenland (denmark)': 'Greenland',
                                    'grenada': 'Grenada', 'guadeloupe (france)': 'Guadeloupe',
                                    'guam (united states of america)': 'Guam', 'guatemala': 'Guatemala',
                                    'guernsey (united kingdom)': 'Guernsey', 'guinea': 'Guinea',
                                    'guinea bissau': 'Guinea-Bissau', 'guyana': 'Guyana', 'haiti': 'Haiti',
                                    'heard island and mcdonald islands': 'Heard Island and McDonald Islands',
                                    'holy see': 'Vatican City', 'honduras': 'Honduras', 'hong kong': 'Hong Kong',
                                    'hungary': 'Hungary', 'iceland': 'Iceland', 'india': 'India',
                                    'indonesia': 'Indonesia',
                                    'islamic republic of iran': 'Iran', 'iraq': 'Iraq', 'ireland': 'Ireland',
                                    'isle of man (united kingdom)': 'Isle of Man', 'israel': 'Israel', 'italy': 'Italy',
                                    'jamaica': 'Jamaica', 'japan': 'Japan', 'jersey (united kingdom)': 'Jersey',
                                    'jordan': 'Jordan', 'kazakhstan': 'Kazakhstan', 'kenya': 'Kenya',
                                    'kiribati': 'Kiribati',
                                    'democratic peoples republic of korea': 'North Korea',
                                    'republic of korea': 'South Korea', 'kuwait': 'Kuwait', 'kyrgyzstan': 'Kyrgyzstan',
                                    'latvia': 'Latvia', 'lebanon': 'Lebanon', 'lesotho': 'Lesotho',
                                    'liberia': 'Liberia',
                                    'libya': 'Libya', 'liechtenstein': 'Liechtenstein', 'lithuania': 'Lithuania',
                                    'luxembourg': 'Luxembourg', 'macao': 'Macao', 'macedonia': 'North Macedonia',
                                    'macedonia (fyrom)': 'North Macedonia', 'madagascar': 'Madagascar',
                                    'malawi': 'Malawi',
                                    'malaysia': 'Malaysia', 'maldives': 'Maldives', 'mali': 'Mali', 'malta': 'Malta',
                                    'marshall islands': 'Marshall Islands', 'martinique': 'Martinique',
                                    'martinique (france)': 'Martinique', 'mauritania': 'Mauritania',
                                    'mauritius': 'Mauritius', 'mayotte (france)': 'Mayotte', 'mexico': 'Mexico',
                                    'republic of moldova': 'Moldova', 'monaco': 'Monaco', 'mongolia': 'Mongolia',
                                    'montenegro': 'Montenegro', 'montserrat': 'Montserrat', 'morocco': 'Morocco',
                                    'mozambique': 'Mozambique', 'myanmar/burma': 'Myanmar (Burma)',
                                    'namibia': 'Namibia',
                                    'nauru': 'Nauru', 'nepal': 'Nepal', 'netherlands': 'Netherlands',
                                    'new caledonia (france)': 'New Caledonia', 'new zealand': 'New Zealand',
                                    'nicaragua': 'Nicaragua', 'niger': 'Niger', 'nigeria': 'Nigeria', 'niue': 'Niue',
                                    'norfolk island': 'Norfolk Island',
                                    'northern mariana islands': 'Northern Mariana Islands', 'norway': 'Norway',
                                    'oman': 'Oman', 'pakistan': 'Pakistan', 'palau': 'Palau',
                                    'palestinian territories': 'Palestine', 'panama': 'Panama',
                                    'papua new guinea': 'Papua New Guinea', 'paraguay': 'Paraguay', 'peru': 'Peru',
                                    'philippines': 'Philippines', 'pitcairn': 'Pitcairn Islands', 'poland': 'Poland',
                                    'portugal': 'Portugal', 'puerto rico': 'Puerto Rico',
                                    'puerto rico (united states of america)': 'Puerto Rico',
                                    'reunion (france)': 'Réunion',
                                    'romania': 'Romania', 'russian federation': 'Russia', 'rwanda': 'Rwanda',
                                    'saint helena, ascension and tristan da cunha': 'St Helena, Ascension and Tristan da Cunha',
                                    'saint kitts and nevis': 'St Kitts & Nevis', 'saint lucia': 'St Lucia',
                                    'saint martin (france)': 'St Martin',
                                    'saint pierre and miquelon': 'St Pierre and Miquelon',
                                    'saint vincent and the grenadines': 'St Vincent and the Grenadines',
                                    'samoa': 'Samoa',
                                    'san marino': 'San Marino', 'sao tome and principe': 'São Tomé and Príncipe',
                                    'saudi arabia': 'Saudi Arabia', 'senegal': 'Senegal', 'serbia': 'Serbia',
                                    'seychelles': 'Seychelles', 'sierra leone': 'Sierra Leone',
                                    'singapore': 'Singapore',
                                    'sint maarten': 'Sint Maarten', 'slovakia': 'Slovakia', 'slovenia': 'Slovenia',
                                    'solomon islands': 'Solomon Islands', 'somalia': 'Somalia',
                                    'south africa': 'South Africa',
                                    'south georgia and the south sandwich islands': 'South Georgia and the South Sandwich Islands',
                                    'south sudan': 'South Sudan', 'spain': 'Spain', 'sri lanka': 'Sri Lanka',
                                    'sudan': 'Sudan', 'suriname': 'Suriname',
                                    'svalbard and jan mayen': 'Svalbard and Jan Mayen', 'swaziland': 'Eswatini',
                                    'sweden': 'Sweden', 'switzerland': 'Switzerland', 'syrian arab republic': 'Syria',
                                    'taiwan': 'Taiwan', 'tajikistan': 'Tajikistan',
                                    'united republic of tanzania': 'Tanzania', 'thailand': 'Thailand',
                                    'timor-leste': 'Timor-Leste', 'togo': 'Togo', 'tokelau': 'Tokelau',
                                    'tonga': 'Tonga',
                                    'trinidad and tobago': 'Trinidad and Tobago', 'tunisia': 'Tunisia',
                                    'turkey': 'Turkey',
                                    'turkmenistan': 'Turkmenistan',
                                    'turks and caicos islands': 'Turks and Caicos Islands',
                                    'tuvalu': 'Tuvalu', 'uganda': 'Uganda', 'ukraine': 'Ukraine',
                                    'united arab emirates': 'United Arab Emirates', 'united kingdom': 'United Kingdom',
                                    'united states minor outlying islands': 'United States Minor Outlying Islands',
                                    'united states of america': 'United States', 'uruguay': 'Uruguay',
                                    'uzbekistan': 'Uzbekistan', 'vanuatu': 'Vanuatu', 'venezuela': 'Venezuela',
                                    'vietnam': 'Vietnam', 'virgin islands (british)': 'British Virgin Islands',
                                    'virgin islands (united states of america)': 'U.S. Virgin Islands',
                                    'wallis and futuna': 'Wallis and Futuna', 'western sahara*': 'Western Sahara',
                                    'yemen': 'Yemen', 'zambia': 'Zambia', 'zimbabwe': 'Zimbabwe',
                                    'lao peoples democratic republic': 'Laos', 'cote divoire': "Côte d'Ivoire",
                                    'kosovo': 'Kosovo'}
        # 国家缩写后缀
        self.country_suffix_dict = {'af': 'Afghanistan', 'fk': 'land Islands', 'al': 'Albania', 'dz': 'Algeria',
                                    'as': 'American Samoa', 'ad': 'Andorra', 'ao': 'Angola', 'ai': 'Anguilla',
                                    'aq': 'Antarctica', 'ag': 'Antigua and Barbuda', 'ar': 'Argentina', 'am': 'Armenia',
                                    'aw': 'Aruba', 'au': 'Australia', 'at': 'Austria', 'az': 'Azerbaijan',
                                    'bs': 'Bahamas',
                                    'bh': 'Bahrain', 'bd': 'Bangladesh', 'bb': 'Barbados', 'by': 'Belarus',
                                    'be': 'Belgium',
                                    'bz': 'Belize', 'bj': 'Benin', 'bm': 'Bermuda', 'bt': 'Bhutan', 'ga': 'Bolivia',
                                    'ba': 'Bosnia and Herzegovina', 'bw': 'Botswana', 'bv': 'Bouvet Island',
                                    'br': 'Brazil',
                                    'io': 'British Indian Ocean Territory', 'bn': 'Brunei Darussalam', 'bg': 'Bulgaria',
                                    'bf': 'Burkina Faso', 'bi': 'Burundi', 'cv': 'Cape Verde', 'kh': 'Cambodia',
                                    'cm': 'Cameroon', 'ca': 'Canada', 'ky': 'Cayman Islands',
                                    'cf': 'Central African Republic', 'td': 'Chad', 'cl': 'Chile', 'cn': 'China',
                                    'cx': 'Christmas Island', 'cc': 'Cocos', 'co': 'Colombia', 'km': 'Comoros',
                                    'cg': 'Congo', 'ck': 'Cook Islands', 'cr': 'Costa Rica', 'hr': 'Croatia',
                                    'cu': 'Cuba',
                                    'cy': 'Cyprus', 'cz': 'Czech Republic', 'dk': 'Denmark', 'dj': 'Djibouti',
                                    'do': 'Dominica', 'ec': 'Ecuador', 'eg': 'Egypt', 'sv': 'El Salvador',
                                    'cq': 'Equatorial Guinea', 'ee': 'Estonia', 'et': 'Ethiopia',
                                    'fo': 'Faroe Islands (Denmark)', 'fj': 'Fiji', 'fi': 'Finland', 'fr': 'France',
                                    'gf': 'French Guiana (France)', 'pf': 'French Polynesia (France)',
                                    'tf': 'French Southern Territories', 'gm': 'Gambia', 'ge': 'Georgia',
                                    'de': 'Germany',
                                    'gh': 'Ghana', 'gi': 'Gibraltar', 'vi': 'Greece', 'gl': 'Grenada',
                                    'gp': 'Guadeloupe (France)', 'gt': 'Guatemala', 'gn': 'Guinea',
                                    'gw': 'Guinea Bissau',
                                    'gy': 'Guyana', 'ht': 'Haiti', 'hm': 'Heard Island and McDonald Islands',
                                    'va': 'Holy See', 'hn': 'Honduras', 'hk': 'Hong Kong', 'hu': 'Hungary',
                                    'is': 'Iceland',
                                    'in': 'India', 'id': 'Indonesia', 'ir': 'Islamic Republic of Iran', 'iq': 'Iraq',
                                    'ie': 'Ireland', 'il': 'Israel', 'it': 'Italy', 'jm': 'Jamaica', 'jp': 'Japan',
                                    'jo': 'Jordan', 'kz': 'Kazakhstan', 'ke': 'Kenya', 'ki': 'Kiribati',
                                    'kp': 'Democratic Peoples Republic of Korea', 'kr': 'Republic of Korea',
                                    'kw': 'Kuwait',
                                    'kg': 'Kyrgyzstan', 'lv': 'Latvia', 'lb': 'Lebanon', 'ls': 'Lesotho',
                                    'lr': 'Liberia',
                                    'ly': 'Libya', 'li': 'Liechtenstein', 'lt': 'Lithuania', 'lu': 'Luxembourg',
                                    'mo': 'Macao', 'mg': 'Madagascar', 'mw': 'Malawi', 'my': 'Malaysia',
                                    'mv': 'Maldives',
                                    'ml': 'Mali', 'mt': 'Malta', 'mh': 'Marshall Islands', 'mq': 'Martinique (France)',
                                    'mr': 'Mauritania', 'mx': 'Mexico', 'fm': 'Micronesia', 'md': 'Republic of Moldova',
                                    'mc': 'Monaco', 'mn': 'Mongolia', 'ms': 'Montserrat', 'ma': 'Morocco',
                                    'mz': 'Mozambique', 'mm': 'Myanmar/Burma', 'na': 'Namibia', 'nr': 'Nauru',
                                    'np': 'Nepal',
                                    'nl': 'Netherlands', 'nc': 'New Caledonia (France)', 'nz': 'New Zealand',
                                    'ni': 'Nicaragua', 'ne': 'Niger', 'ng': 'Nigeria', 'nu': 'Niue',
                                    'nf': 'Norfolk Island',
                                    'mp': 'Northern Mariana Islands', 'no': 'Norway', 'om': 'Oman', 'pk': 'Pakistan',
                                    'pw': 'Palau', 'pa': 'Panama', 'pg': 'Papua New Guinea', 'py': 'Paraguay',
                                    'pe': 'Peru',
                                    'ph': 'Philippines', 'pn': 'Pitcairn', 'pl': 'Poland', 'pt': 'Portugal',
                                    'qa': 'Qatar',
                                    're': 'Reunion (France)', 'ro': 'Romania', 'ru': 'Russian Federation',
                                    'rw': 'Rwanda',
                                    'kn': 'Saint Kitts and Nevis', 'sh': 'Saint Lucia',
                                    'pm': 'Saint Pierre and Miquelon',
                                    'vc': 'Saint Vincent and the Grenadines', 'sm': 'San Marino',
                                    'st': 'Sao Tome and Principe', 'sa': 'Saudi Arabia', 'sn': 'Senegal',
                                    'sc': 'Seychelles',
                                    'sl': 'Sierra Leone', 'sg': 'Singapore', 'sk': 'Slovakia', 'si': 'Slovenia',
                                    'sb': 'Solomon Islands', 'so': 'Somalia', 'za': 'South Africa', 'ss': 'South Sudan',
                                    'es': 'Spain', 'lk': 'Sri Lanka', 'sd': 'Sudan', 'sr': 'Suriname',
                                    'sz': 'Swaziland',
                                    'se': 'Sweden', 'ch': 'Switzerland', 'sy': 'Syrian Arab Republic', 'tw': 'Taiwan',
                                    'tj': 'Tajikistan', 'tz': 'United Republic of Tanzania', 'th': 'Thailand',
                                    'tl': 'Timor-Leste', 'tg': 'Togo', 'tk': 'Tokelau', 'to': 'Tonga',
                                    'tt': 'Trinidad and Tobago', 'tn': 'Tunisia', 'tr': 'Turkey', 'tm': 'Turkmenistan',
                                    'tc': 'Turks and Caicos Islands', 'tv': 'Tuvalu', 'ug': 'Uganda', 'ua': 'Ukraine',
                                    'ae': 'United Arab Emirates', 'uk': 'United Kingdom',
                                    'pr': 'United States Minor Outlying Islands', 'us': 'United States of America',
                                    'uy': 'Uruguay', 'vu': 'Vanuatu', 've': 'Venezuela', 'vn': 'VietNam',
                                    'vg': 'Virgin Islands (British)', 'wf': 'Wallis and Futuna',
                                    'ws': 'Western Sahara*',
                                    'ye': 'Yemen', 'zm': 'Zambia', 'zw': 'Zimbabwe',
                                    'la': 'Lao Peoples Democratic Republic',
                                    'ci': 'COTE DIVOIRE'}

    # 纯纬度上，度数差转距离
    def lat_degree2km(self, dif_degree=.0001, radius=None):
        """
        通过圆环求法，纯纬度上，度数差转距离(km)，与中间点所处的地球上的位置关系不大
        :param dif_degree: 度数差, 经验值0.0001对应11.1米的距离
        :param radius: 圆环求法的等效半径，纬度距离的等效圆环是经线环，所以默认都是earth_radius
        :return: 这个度数差dif_degree对应的距离，单位km
        """
        if not radius:
            radius = self.earth_radius
        return radius * dif_degree * self.pis_per_degree

    # 纯纬度上，距离值转度数
    def lat_km2degree(self, dis_km=111, radius=None):
        """
        通过圆环求法，纯纬度上，距离值转度数(diff)，与中间点所处的地球上的位置关系不大
        :param dis_km: 输入的距离，单位km，经验值111km相差约(接近)1度
        :param radius: 圆环求法的等效半径，纬度距离的等效圆环是经线环，所以默认都是earth_radius
        :return: 这个距离dis_km对应在纯纬度上差多少度
        """
        if not radius:
            radius = self.earth_radius
        return dis_km / radius / self.pis_per_degree

    def lng_degree2km(self, dif_degree=.0001, center_lat=22):
        """
        通过圆环求法，纯经度上，度数差转距离(km)，纬度的高低会影响距离对应的经度角度差，具体表达式为：
        :param dif_degree: 度数差
        :param center_lat: 中心点的纬度，默认22为深圳附近的纬度值；为0时表示赤道，赤道的纬线环半径使得经度计算和上面的纬度计算基本一致
        :return: 这个度数差dif_degree对应的距离，单位km
        """
        # 修正后，中心点所在纬度的地表圆环半径
        real_radius = self.earth_radius * math.cos(center_lat * self.pis_per_degree)
        return self.lat_degree2km(dif_degree, real_radius)

    def lng_km2degree(self, dis_km=1, center_lat=22):
        """
        纯经度上，距离值转角度差(diff)，单位度数。
        :param dis_km: 输入的距离，单位km
        :param center_lat: 中心点的纬度，默认22为深圳附近的纬度值；为0时表示赤道。赤道、中国深圳、中国北京、对应的修正系数分别约为： 1  0.927  0.766
        :return: 这个距离dis_km对应在纯经度上差多少度
        """
        # 修正后，中心点所在纬度的地表圆环半径
        real_radius = self.earth_radius * math.cos(center_lat * self.pis_per_degree)
        return self.lat_km2degree(dis_km, real_radius)

    # 调整1d，moudle1：步幅0.01，moudle0：步幅1
    def get_1d(self, module=1, offset=0.01):
        a = []
        # z=2 1d值
        ori = 94618532.08008283
        a.append([2, ori])
        for i in range(2, 22):
            if i > 2:
                ori = (ori / 2)
            else:
                ori = ori
            if module == 1:
                for j in np.arange(0, 1, offset):
                    if (i + j) > 2 and (i + j) <= 21:
                        # print((i+j),ori - ori*j/2)
                        a.append([(i + j), ori - ori * j / 2])
            elif module == 0:
                if [i, ori] not in a:
                    a.append([i, ori])
        return dict(a)

    # 调整经纬度
    # d3为纬度，范围[-85.05112877980659, 85.05112877980659]
    # d2为经度，范围 [-180, 180]
    def get_23d(self, d2, d3, dis=5775.056889653493):
        # 默认经纬度步幅，取缩放倍数16的1d
        # 取值范围
        lat_range = [-85.05112877980659, 85.05112877980659]
        lon_range = [-180, 180]

        lat = self.lat_km2degree(int(dis / 1000))
        lon = self.lng_km2degree(int(dis / 1000), d3)
        # print(lat, lon)
        up = (d2, d3 + lat) if -85.05112877980659 < d3 + lat < 85.05112877980659 else None
        down = (d2, d3 - lat) if -85.05112877980659 < d3 - lat < 85.05112877980659 else None
        left = (d2 - lon, d3) if -180 < d2 - lon < 180 else None
        right = (d2 + lon, d3) if -180 < d2 + lon < 180 else None

        return [up, down, left, right]

    def get_search_url(self, lon, lat, search_key):
        """
        获取搜索url
        Args:
            lon: 经度
            lat: 维度
            search_key: 搜索的关键词

        Returns:
            google搜索url
        """
        params = {
            "tbm": "map",
            "authuser": "0",
            "hl": "zh-CN",
            "gl": "sg",
            "pb": f"!4m12!1m3!1d305467.63937510963!2d{lon}!3d{lat}!2m3!1f0!2f0!3f0!3m2!1i1920!2i919!4f13.1!7i20!10b1!12m17!1m1!18b1!2m3!5m1!6e2!20e3!10b1!12b1!13b1!16b1!17m1!3e1!20m4!5e2!6b1!8b1!14b1!19m4!2m3!1i360!2i120!4i8!20m57!2m2!1i203!2i100!3m2!2i4!5b1!6m6!1m2!1i86!2i86!1m2!1i408!2i240!7m42!1m3!1e1!2b0!3e3!1m3!1e2!2b1!3e2!1m3!1e2!2b0!3e3!1m3!1e8!2b0!3e3!1m3!1e10!2b0!3e3!1m3!1e10!2b1!3e2!1m3!1e9!2b1!3e2!1m3!1e10!2b0!3e3!1m3!1e10!2b1!3e2!1m3!1e10!2b0!3e4!2b1!4b1!9b0!22m6!1sb8qkZdGXCLi64-EPkIyK-Ag:4!2s1i:0,t:11886,p:b8qkZdGXCLi64-EPkIyK-Ag:4!7e81!12e5!17sb8qkZdGXCLi64-EPkIyK-Ag:29!18e15!24m94!1m29!13m9!2b1!3b1!4b1!6i1!8b1!9b1!14b1!20b1!25b1!18m18!3b1!4b1!5b1!6b1!9b1!12b1!13b1!14b1!15b1!17b1!20b1!21b1!22b1!25b1!27m1!1b0!28b0!31b0!10m1!8e3!11m1!3e1!14m1!3b1!17b1!20m2!1e3!1e6!24b1!25b1!26b1!29b1!30m1!2b1!36b1!39m3!2m2!2i1!3i1!43b1!52b1!54m1!1b1!55b1!56m2!1b1!3b1!65m5!3m4!1m3!1m2!1i224!2i298!71b1!72m17!1m5!1b1!2b1!3b1!5b1!7b1!4b1!8m8!1m6!4m1!1e1!4m1!1e3!4m1!1e4!3sother_user_reviews!9b1!89b1!103b1!113b1!114m3!1b1!2m1!1b1!117b1!122m1!1b1!26m4!2m3!1i80!2i92!4i8!30m28!1m6!1m2!1i0!2i0!2m2!1i530!2i919!1m6!1m2!1i1870!2i0!2m2!1i1920!2i919!1m6!1m2!1i0!2i0!2m2!1i1920!2i20!1m6!1m2!1i0!2i899!2m2!1i1920!2i919!34m18!2b1!3b1!4b1!6b1!8m6!1b1!3b1!4b1!5b1!6b1!7b1!9b1!12b1!14b1!20b1!23b1!25b1!26b1!37m1!1e81!42b1!47m0!49m7!3b1!6m2!1b1!2b1!7m2!1e3!2b1!50m4!2e2!3m2!1b1!3b1!61b1!67m2!7b1!10b1!69i676",
            "q": search_key,
            "oq": search_key,
            "gs_l": "maps.3..38i444k1j38i426k1l2j38j38i426k1.25247.25247.1.26440.1.1.....150.150.0j1.1.....0....1..maps..0.1.160.0.",
            "tch": 1,
            "ech": 1,
            "psi": "b8qkZdGXCLi64-EPkIyK-Ag.1705298544574.1"
        }
        url = 'https://www.google.com/search'
        return url + '?' + urlencode(params)

    def get_all_result(self, response):
        """
        解析搜索链接返回的数据
        Args:
            response: requests请求对象

        Returns:
            List[dict]
            phone_id 媒体数据文件的id
        """
        page_source = response.text
        big_dict = json.loads(page_source.replace('/*""*/', ''))
        d_str = big_dict['d'].replace(")]}'", '').strip()
        d_list = json.loads(d_str)
        company_list = d_list[0][1]
        result_list = list()
        if company_list:
            for company in company_list:
                try:
                    temp_dict = dict()
                    if len(company) > 14:
                        temp_dict['companyName'] = company[14][11] if company and company[14] and company[14][
                            11] else None
                        temp_dict['url'] = company[14][7][0] if company and company[14] and company[14][7] and \
                                                                company[14][7][
                                                                    0] else None
                        if company[14][10]:
                            temp_dict['phone_id'] = company[14][10]
                        if temp_dict['url']:
                            # temp_dict['url'] = unquote(temp_dict['url'])
                            temp_dict['url'] = temp_dict['url']
                        temp_dict['address'] = company[14][39] if company and company[14] and company[14][39] else None
                        if not temp_dict['address']:
                            temp_dict['address'] = company[14][18] if company and company[14] and company[14][
                                18] else None
                        temp_dict['phone'] = company[14][178][0][0] if company and company[14] and company[14][178] and \
                                                                       company[14][178][0] and company[14][178][0][
                                                                           0] else None
                        if not temp_dict['phone']:
                            temp_dict['phone'] = company[14][3][0] if company and company[14] and company[14][3] and \
                                                                      company[14][3][0] else None
                        temp_dict['category'] = '>'.join(company[14][13]) if company and company[14] and company[14][
                            13] else None
                        temp_dict['countryEn'] = None
                        if temp_dict['address']:
                            for google_country in self.google_country_dict.values():
                                if google_country.lower() in temp_dict['address'].lower():
                                    temp_dict['countryEn'] = google_country
                                    break
                        if not temp_dict['countryEn']:
                            if company[14] and company[14][183] and company[14][183][1] and company[14][183][1][
                                -1].lower() in self.country_suffix_dict.keys():
                                temp_dict['countryEn'] = self.country_suffix_dict[company[14][183][1][-1].lower()]
                        temp_dict['city'] = company[14][14] if company and company[14] and company[14][14] else None
                        if temp_dict['companyName']:
                            # yield temp_dict
                            result_list.append(temp_dict)

                except Exception as e:
                    print('error ', e)
                    continue
        return result_list

    def get_photo_url(self, phone_id):
        """
        使用phone_id获取媒体文件的请求url
        Args:
            phone_id: 媒体id

        Returns:
            媒体请求的链接地址
        """
        params = {
            "authuser": 0,
            "hl": "zh-CN",
            "gl": 'gl',
            "pb": f'!1e2!3m3!1s{phone_id}!9e0!11zL20vMDMyOG15!5m50!2m2!1i203!2i100!3m2!2i20!5b1!7m42!1m3!1e1!2b0!3e3!1m3!1e2!2b1!3e2!1m3!1e2!2b0!3e3!1m3!1e8!2b0!3e3!1m3!1e10!2b0!3e3!1m3!1e10!2b1!3e2!1m3!1e9!2b1!3e2!1m3!1e10!2b0!3e3!1m3!1e10!2b1!3e2!1m3!1e10!2b0!3e4!2b1!4b1!9b0!6m3!1sb8qkZdGXCLi64-EPkIyK-Ag!7e81!15i16698!16m2!2b1!4e1'
        }
        url = 'https://www.google.com/maps/rpc/photo/listentityphotos'
        return url + '?' + urlencode(params)

    def group_data(self, all_data: List[dict], other_mapping: dict = None):
        """
        对数据进行处理，处理出当前已知的视频、图片、街景id
        type1=10 type2=10   视频
        type1=10 type2=12   图片
        type1=0 type2=2    街景id
        type1=10 type2=11    街景id
        Args:
            all_data:
            other_mapping:

        Returns:

        """
        mapping = {
            (10, 10): 'video',
            (10, 12): 'images',
            (0, 2): 'streetscape',
            (10, 11): 'streetscape'
        }
        if other_mapping:
            mapping.update(other_mapping)

        end_data = {'images': [], 'video': [], 'streetscape': [], 'other': []}

        for data in all_data:
            key = mapping.get((data.get('type1'), data.get('type2')), 'other')
            end_data[key].append(data)

        return end_data

    def get_medium(self, json_data):
        """
        解析媒体数据
        Args:
            json_data:

        Returns:

        """
        # 解析街景或图片
        page_date = [dict(pid=data[0], type1=data[1], type2=data[2]) for data in json_data[0]]
        # 处理下面的分类数据
        data_12 = json_data[12][0] if json_data[12] else None
        if data_12:
            for data in data_12:
                if any(l in data[2].strip() for l in ['街景']):
                    if data[3][0][0] in [ll.get('pid') for ll in page_date]:
                        continue
                    # 此时说明有街景的数据
                    page_date = page_date if page_date else []
                    page_date.append({
                        "pid": data[3][0][0],
                        "type1": 0,
                        "type2": 2
                    })
            # 如果存在下标为12的，就说明出现了其他请求的参数
            group_data = [{'key': i[0].replace('=', ''), 'name': i[2]} for i in data_12 if
                          i and len(i) >= 2 and i[0] != 'CgIgAQ==']
        else:
            group_data = []
        if page_date:
            page_date = self.group_data(page_date)
        else:
            page_date = None

        return page_date, group_data

    def analysis_photo_list(self, response, phone_id):
        """
        解析媒体数据，并计算出当前的下一页的数据，
        TIP：不同的小分组的数据可以使用当前方法进行数据解析，但是不能使用这个方法的next_url
        Args:
            response:
            phone_id:

        Returns:

        """
        page_source = response.text
        page_source = page_source.replace(")]}'", '').strip()
        json_data = json.loads(page_source)
        next_url_params = json_data[5] if len(json_data) > 5 else None
        if next_url_params:
            params = {
                "authuser": 0,
                "hl": "zh-CN",
                "gl": 'gl',
                "pb": f'!1e2!3m3!1s{phone_id}!9e0!11zL20vMDgxc3E!5m51!2m2!1i203!2i100!3m3!2i20!3s{next_url_params}!5b1!7m42!1m3!1e1!2b0!3e3!1m3!1e2!2b1!3e2!1m3!1e2!2b0!3e3!1m3!1e8!2b0!3e3!1m3!1e10!2b0!3e3!1m3!1e10!2b1!3e2!1m3!1e9!2b1!3e2!1m3!1e10!2b0!3e3!1m3!1e10!2b1!3e2!1m3!1e10!2b0!3e4!2b1!4b1!9b0!6m3!1sSSGmZb6ZN6jQ2roPo92PcA!7e81!15i16698!16m2!2b1!4e1'
            }
            next_url = 'https://www.google.com/maps/rpc/photo/listentityphotos' + '?' + urlencode(params)
        else:
            next_url = None

        # 解析街景或图片
        page_date, group_data = self.get_medium(json_data=json_data)

        return page_date, next_url, group_data

    def analysis_group_photo_list(self, response, phone_id, group_key):
        """
        解析分组媒体数据，并计算出当前的下一页的数据，
        Args:
            response:
            phone_id:
            group_key:

        Returns:

        """
        page_source = response.text
        page_source = page_source.replace(")]}'", '').strip()
        json_data = json.loads(page_source)
        next_url_params = json_data[5] if len(json_data) > 5 else None
        if next_url_params:
            params = {
                "authuser": 0,
                "hl": "zh-CN",
                "gl": 'sg',
                "pb": f'!1e2!3m3!1s{phone_id}!9e0!11s/m/01113ych!5m51!2m2!1i203!2i100!3m3!2i20!3s{next_url_params}!5b1!7m42!1m3!1e1!2b0!3e3!1m3!1e2!2b1!3e2!1m3!1e2!2b0!3e3!1m3!1e8!2b0!3e3!1m3!1e10!2b0!3e3!1m3!1e10!2b1!3e2!1m3!1e9!2b1!3e2!1m3!1e10!2b0!3e3!1m3!1e10!2b1!3e2!1m3!1e10!2b0!3e4!2b1!4b1!9b0!6m3!1suLGnZZfyBbSIjuMP-KGsmAE!7e81!15i16698!16m4!1m1!1B{group_key}!2b1!4e1'
            }
            next_url = 'https://www.google.com/maps/rpc/photo/listentityphotos' + '?' + urlencode(params)
        else:
            next_url = None

        # 解析街景或图片
        page_date, group_data = self.get_medium(json_data=json_data)

        return page_date, next_url, group_data

    def get_type_url(self):
        """
        获取限制已知的数据拼接方式
        Returns:

        """
        return {
            "images": 'https://lh5.googleusercontent.com/p/{pid}=s4096-k-no',
            "video": "https://lh3.googleusercontent.com/ggs/{pid}=m22",
            "streetscape": "https://lh3.ggpht.com/p/{pid}"  # 有概率不一样
        }

    def group_url(self, group_key, phone_id):
        """
        获取不同分组的数据
        Args:
            group_key:
            phone_id:

        Returns:

        """
        if group_key and phone_id:
            params = {
                "authuser": 0,
                "hl": "zh-CN",
                "gl": 'sg',
                "pb": f'!1e2!3m3!1s{phone_id}!9e0!11s/m/01113ych!5m50!2m2!1i203!2i100!3m2!2i20!5b1!7m42!1m3!1e1!2b0!3e3!1m3!1e2!2b1!3e2!1m3!1e2!2b0!3e3!1m3!1e8!2b0!3e3!1m3!1e10!2b0!3e3!1m3!1e10!2b1!3e2!1m3!1e9!2b1!3e2!1m3!1e10!2b0!3e3!1m3!1e10!2b1!3e2!1m3!1e10!2b0!3e4!2b1!4b1!9b0!6m3!1sZKKnZYfiLvqb4-EPjdi6yAo!7e81!15i16698!16m4!1m1!1B{group_key}!2b1!4e1'
            }
            next_url = 'https://www.google.com/maps/rpc/photo/listentityphotos' + '?' + urlencode(params)
        else:
            next_url = None
        return next_url


# 使用demo

# if __name__ == '__main__':
#     import random, requests
#
#     target_info = TargetInfo()
#
#     def get_(url):
#         response = requests.get(url, proxies=proxies, headers=headers)
#         page_date, next_url, group_data = target_info.analysis_photo_list(response, phone_id)
#         return {
#             "page_date": page_date,
#             "next_url": next_url,
#             "group_data": group_data
#         }
#
#
#     proxies = {
#         "http": 'http://192.168.1.204:7891',
#         "https": 'http://192.168.1.204:7891',
#     }
#     agents = [
#         'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36',
#         'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.0.249.0 Safari/532.5',
#         'Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/532.9 (KHTML, like Gecko) Chrome/5.0.310.0 Safari/532.9',
#         'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.514.0 Safari/534.7',
#         'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/534.14 (KHTML, like Gecko) Chrome/9.0.601.0 Safari/534.14',
#         'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.14 (KHTML, like Gecko) Chrome/10.0.601.0 Safari/534.14',
#         'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.20 (KHTML, like Gecko) Chrome/11.0.672.2 Safari/534.20", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.27 (KHTML, like Gecko) Chrome/12.0.712.0 Safari/534.27',
#         'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.24 Safari/535.1']
#     headers = {'User-Agent': random.choice(agents)}
#     lon = '88.61333333'
#     lat = '27.33'
#     search_key = 'Thakurbari Temple, Gangtok'
#     url = target_info.get_search_url(lon=lon, lat=lat, search_key=search_key)
#     response = requests.get(url, proxies=proxies, headers=headers)
#     response_data = target_info.get_all_result(response)
#     print(response_data)
#     # 获取图片url
#     phone_id = response_data[0].get('phone_id')
#     phone_url = target_info.get_photo_url(phone_id)
#     data = get_(phone_url)
#     # group_data
#     group_data = data.get('group_data')
#     keys = group_data[1].get('key')
#     # 获取group的url
#     group_url = target_info.group_url(group_key=keys, phone_id=phone_id)
#     # 获取group的response
#     group_response = requests.get(group_url, proxies=proxies, headers=headers)
#     # 解析group的数据
#     grop_data = target_info.analysis_group_photo_list(response=group_response, phone_id=phone_id, group_key=keys)
#     print()
